package com.jdk._05_StreamAPI;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Stream
 * 位于 java.util.stream 包下
 * 流操作分为 3个步骤，1.创建流，2.定义中间操作，3.执行操作返回结果
 * <p>
 * 创建流
 * Stream<Integer> stream1 = Arrays.asList(1, 2, 3).stream();
 * Stream<Integer> stream2 = Stream.of(1, 2, 3);
 * Stream<Integer> stream3 = Stream.iterate(1, (i) -> i + 1).limit(3);
 * <p>
 * 中间操作
 * 【过滤】【filter】
 * 【映射】【map】【mapToInt】【mapToLong】【mapToDouble】
 * 【聚合操作】【max】【sum】【min】
 * 【去重】【distinct】
 * 【排序】【distinct】
 * 【查看】【peek】
 * 【限制】【limit】
 * 【丢弃】【skip】
 * 【遍历】【forEach】
 * 【递归结合元素，返回结果继续传入】【类比大数据中的 map-reduce模式】【reduce】
 */
public class _Test {


    public static void main(String[] args) {
        //创建流的三种形式
        //Stream<Integer> stream1 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).stream();
        //Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        //Stream<Integer> stream3 = Stream.iterate(1, (i) -> i + 1).limit(10);

        List<People> list =
                Arrays.asList(
                        new People(1, "一"),
                        new People(2, "二"),
                        new People(3, "三"),
                        new People(4, "四"),
                        new People(5, "五"),
                        new People(9, "九"),
                        new People(9, "九"),
                        new People(8, "八"),
                        new People(7, "七"),
                        new People(6, "六")
                );

        /**
         * 【过滤】【filter】
         * 场景：过滤年龄大于3的人，返回集合
         * 输出：[People（4,四）, People（5,五）, People（9,九）, People（9,九）, People（8,八）, People（7,七）, People（6,六）]
         */
        List<People> collect = list.stream().filter(people -> people.getAge() > 3).collect(Collectors.toList());
        System.out.println(collect);

        /**
         * 【映射】【map】
         * 场景：返回对象的姓名集合
         * 输出：[一, 二, 三, 四, 五, 九, 九, 八, 七, 六]
         */
        List<String> collect1 = list.stream().map(people -> people.getName()).collect(Collectors.toList());
        System.out.println(collect1);

        /**
         * 【映射】【mapToInt】【mapToLong】【mapToDouble】
         * 【聚合操作】【max】【sum】【min】
         * 场景：返回 年龄最大值、最小值、总和
         * 输出：1 9 54  ;  1 9 54  ;  1.0 9.0 54.0
         */
        OptionalInt max = list.stream().mapToInt(people -> people.getAge()).max();
        OptionalInt min = list.stream().mapToInt(people -> people.getAge()).min();
        int sum = list.stream().mapToInt(people -> people.getAge()).sum();
        System.out.print(min.getAsInt() + " " + max.getAsInt() + " " + sum + "  ;  ");
        //
        OptionalLong max1 = list.stream().mapToLong(people -> people.getAge()).max();
        OptionalLong min1 = list.stream().mapToLong(people -> people.getAge()).min();
        long sum1 = list.stream().mapToLong(people -> people.getAge()).sum();
        System.out.print(min1.getAsLong() + " " + max1.getAsLong() + " " + sum1 + "  ;  ");
        //
        OptionalDouble max2 = list.stream().mapToDouble(people -> people.getAge()).max();
        OptionalDouble min2 = list.stream().mapToDouble(people -> people.getAge()).min();
        double sum2 = list.stream().mapToDouble(people -> people.getAge()).sum();
        System.out.print(min2.getAsDouble() + " " + max2.getAsDouble() + " " + sum2 + "\n");

        /**
         * 【映射并返回流】【mapToInt】
         * 场景：将每个年龄加1，返回年龄数组
         * 输出：[2, 3, 4, 5, 6, 10, 10, 9, 8, 7]
         */
        List<Integer> collect2 = list.stream().flatMap(people -> Stream.of(people.getAge() + 1)).collect(Collectors.toList());
        System.out.println(collect2);

        /**
         * 【去重】【distinct】
         * 场景：输出去重后的，全部姓名集合
         * 输出：[一, 二, 三, 四, 五, 九, 八, 七, 六]
         */
        List<String> collect3 = list.stream().map(people -> people.getName()).distinct().collect(Collectors.toList());
        System.out.println(collect3);

        /**
         * 【排序】【distinct】
         * 场景：输出按年龄降序排列后的集合
         * 输出：[People（9,九）, People（9,九）, People（8,八）, People（7,七）, People（6,六）, People（5,五）, People（4,四）, People（3,三）, People（2,二）, People（1,一）]
         */
        List<People> collect4 = list.stream().sorted((p1, p2) -> p2.getAge() - p1.getAge()).collect(Collectors.toList());
        System.out.println(collect4);

        /**
         * 【查看】【peek】
         * 场景：输出所有人员信息
         * 输出：[People（9,九）, People（9,九）, People（8,八）, People（7,七）, People（6,六）, People（5,五）, People（4,四）, People（3,三）, People（2,二）, People（1,一）]
         */
        Stream<People> peek = list.stream().peek(people -> System.out.println(people));

        /**
         * 【限制】【limit】
         * 场景：输出前三个元素
         * 输出：[People（1,一）, People（2,二）, People（3,三）]
         */
        List<People> collect6 = list.stream().limit(3).collect(Collectors.toList());
        System.out.println(collect6);

        /**
         * 【丢弃】【skip】
         * 场景：丢弃前5个元素
         * 输出：[People（9,九）, People（9,九）, People（8,八）, People（7,七）, People（6,六）]
         */
        List<People> collect5 = list.stream().skip(5).collect(Collectors.toList());
        System.out.println(collect5);

        /**
         * 【遍历】【forEach】
         * 场景：丢弃前5个元素
         * 输出：People（1,一）People（2,二）People（3,三）People（4,四）People（5,五）People（9,九）People（9,九）People（8,八）People（7,七）People（6,六）
         */
        list.stream().forEach(people -> System.out.print(people));
        System.out.println();

        /**
         * 【递归结合元素，返回结果继续传入】【类比大数据中的 map-reduce模式】【reduce】
         * 场景：获得总年龄
         * 输出：54
         */
        Integer reduce = list.stream().map(people -> people.getAge()).reduce(0, (a, b) -> a + b);
        System.out.println(reduce);

    }


    //【过滤】【filter】
    //【跳过】【skip】
    //【截断】【limit】
    //【映射】【map、flatMap】
    //【去重】【distinct】
    //【排序】【sorted】
    //【校验】【allMatch、anyMatch、noneMatch】
    //【匹配】【findFirst、findAny】
    //【匹配】【count】
    //【数量】【max、min】
    //【规约】【reduce】
    //【收集】【collect】
    //【分组】【collect】
    //【分区】【collect】
    //【汇总】【collect】
    //【拼接】【collect】
}

